<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>bind</title>
</head>
<body>
    <script>
        console.log('手写bind');

        // 重写函数的bind方法
        /**
         * bind方法应该返回一个新函数
         * arguments 是一个对应于传递给函数的参数的类数组对象 (伪数组)。
         * arguments对象是所有（非箭头）函数中都可用的局部变量
         */
        Function.prototype.bind = function() {
            // 函数的默认参数是arguments
            const obj = arguments[0];
            const args = [];
            if (arguments.length > 1) {
                for (let index = 1; index < arguments.length; index++) {
                    args.push(arguments[index]);
                }
            }
            const self = this; // fn
            return function () { // 返回的新函数
                for (let index = 0; index < arguments.length; index++) {
                    args.push(arguments[index]);
                }
                self.apply(obj, args);
            };
        }



        function fn(a, b) {
            console.log(a, b, this.m);
        }

        const obj = {m: 1};

        /**
         * call, 第一个是参数是对象，后面是参数序列
         * apply, 第一个参数是对象， 后面是参数数组
         * bind, 创建一个新函数，新函数的this是第一个参数， 其余参数作为新函数的参数
         */
        fn.call(obj, 2, 3);
        fn.apply(obj, [ 2, 3]);
        fn.bind(obj)(2, 3);

        const fn2 = fn.bind(obj, 5); // 这个时候，fn2默认已经有1个参数了，就是5
        fn2();
        const fn4 = fn.bind(obj, 5); // 这个时候，fn2默认已经有1个参数了，就是5
        fn4(7); //fn4已经默认有一个参数5了，执行时再加一个参数7

        const fn3 = fn.bind(obj, 5, 6); // fn3默认已经有2个参数了，就是 5, 6
        fn3();
        

        
    </script>
</body>
</html>